package controllers.GestionComponentes;

import models.*;
import models.Hidpuntomonitoreo;
import play.mvc.Controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Daniel
 * Date: 17/07/12
 * Time: 11:24 AM
 * To change this template use File | Settings | File Templates.
 */
public class GestorComponentes extends Controller{

    public static void index(int id, double latimaxima, double longmaxima, double latiminima, double longminima)
    {
        int idmodelo = id;
        double latmax = latimaxima;
        double longmax = longmaxima;
        double latmin = latiminima;
        double longmin = longminima;

        //se debe obtener todos los componentes de un modelo de simulacion dado
        List<Hidcomponente> hidcomponentes = Hidcomponente.find("byModsimid",idmodelo).fetch();

        //se debe almacenar los atributos de los componentes en cadenas de texto a modo
        //de listas, es decir cada atributo serparado por algun delimitador (",")
        String latitudesComponentes = "";
        String longitudesComponentes = "";
        String nombresComponentes = "";
        String tipos = "";
        String tiposuni = "";
        String ids = "";
        String aristas = "";
        String tipoptomon = "";

        for(int i = 0; i < hidcomponentes.size(); i++)
        {
            latitudesComponentes += hidcomponentes.get(i).getComplati() + ",";
            longitudesComponentes += hidcomponentes.get(i).getComplong() + ",";
            nombresComponentes += hidcomponentes.get(i).getCompnom() + ",";
            tipos += hidcomponentes.get(i).getHidtipocomponente().getTipcompnom() + ",";
            tiposuni += hidcomponentes.get(i).getHidtipocomponente().isTipcompuni() + ",";

            //si se trata de un componente que no es singular (aristas) se alamacenan en una nueva cadena de texto
            //dedicada para las aristas
            if(hidcomponentes.get(i).getHidtipocomponente().isTipcompuni() == false)
            {
                aristas += obtenerArista(hidcomponentes.get(i).getCompid()) + ";";
            }
            ids += hidcomponentes.get(i).getCompid() + ",";

            //se debe almacenar los puntos de monitoreo para cada componente
            Hidpuntomonitoreo hidpuntomonitoreo = Hidpuntomonitoreo.find("compid = ?", hidcomponentes.get(i).getCompid()).first();
            tipoptomon += hidpuntomonitoreo.getHidtipopuntomonitoreo().getTippunmonid() + ",";
        }


        //para cada punto de monitoreo se debe obtener sus atributos
        List<Hidtipopuntomonitoreo> hidtipopuntomonitoreos = Hidtipopuntomonitoreo.findAll();
        String idstipoptomon = "";
        String nomtipoptomon = "";

        for (int i = 0; i < hidtipopuntomonitoreos.size(); i++)
        {
            idstipoptomon += hidtipopuntomonitoreos.get(i).getTippunmonid() + ",";
            nomtipoptomon += hidtipopuntomonitoreos.get(i).getTippunmonnom() + ",";
        }

        render(idmodelo, latmax, longmax, latmin, longmin, latitudesComponentes, longitudesComponentes, tipos, tiposuni, ids, aristas, nombresComponentes, idstipoptomon, nomtipoptomon, tipoptomon);
    }

    public static void agregarComponentes(int idmodelo, String latitudes, String longitudes,
                                          String tiposdecomponente, String idescomponente, String ideliminados,
                                          double latimaxima, double longmaxima, double latiminima, double longminima,
                                          String lineas, String nombrescomponentes, String idstipptomon)
    {
        String delimitador = ",";
        String[] latitud = latitudes.split(delimitador);
        String[] longitud = longitudes.split(delimitador);
        String[] tipos = tiposdecomponente.split(delimitador);
        String[] ides = idescomponente.split(delimitador);
        String[] nombres = nombrescomponentes.split(delimitador);
        String[] tipptomon = idstipptomon.split(delimitador);
        String[] eliminados;

        AgregarComponentesNodos(tipos, idmodelo, ides, latitud, longitud, tiposdecomponente, nombres, tipptomon);
        AgregarPolyLines(lineas,idmodelo);
        EliminarComponentes(ideliminados);
        index(idmodelo,latimaxima,longmaxima,latiminima,longminima);
    }

    public static int AgregarComponentesNodos(String[] tipos, int idmodelo, String[] ides,
                                              String[] latitud, String[] longitud, String tiposdecomponente,
                                              String[] nombres, String[] tipptomon)
    {
        if (tiposdecomponente.equals("") == false)
        {
            for (int i = 0; i < tipos.length; i++)
            {
                Hidcomponente hidcomponente;
                Hidnodo hidnodo;
                Hidpuntomonitoreo hidpuntomonitoreo;

                Hidtipocomponente hidtipocomponente = Hidtipocomponente.find("byTipcompnom",tipos[i]).first();
                Hidmodelosimulacion hidmodelosimulacion = Hidmodelosimulacion.findById(idmodelo);
                Hidtipopuntomonitoreo hidtipopuntomonitoreo = Hidtipopuntomonitoreo.findById(Integer.valueOf(tipptomon[i]));

                if(Hidcomponente.findById(Integer.valueOf(ides[i])) != null)
                {
                    hidcomponente = Hidcomponente.findById(Integer.valueOf(ides[i]));
                    //       hidnodo = Hidnodo.find("byCompid",Integer.valueOf(ides[i])).first();
                    hidpuntomonitoreo = Hidpuntomonitoreo.find("byCompid", Integer.valueOf(ides[i])).first();
                }
                else
                {
                    hidcomponente = new Hidcomponente();

                    // hidcomponente.setCompid(Integer.valueOf(ides[i]));
                    hidcomponente.setCompnom(nombres[i]);
                    hidcomponente.setHidmodelosimulacion(hidmodelosimulacion);
                    hidcomponente.setHidtipocomponente(hidtipocomponente);

                    hidnodo = new Hidnodo();
                    hidnodo.setHidcomponente(hidcomponente);

                    hidpuntomonitoreo = new Hidpuntomonitoreo();
                    hidpuntomonitoreo.setHidcomponente(hidcomponente);
                    hidpuntomonitoreo.setHidtipopuntomonitoreo(hidtipopuntomonitoreo);
                    BigDecimal bdlat= new BigDecimal(latitud[i]);
                    BigDecimal bdlng= new BigDecimal(longitud[i]);
                    hidcomponente.setComplati(bdlat);
                    hidcomponente.setComplong(bdlng);

                    hidcomponente.save();
                    hidpuntomonitoreo.save();
                    hidnodo.save();
                }

                BigDecimal bdlat= new BigDecimal(latitud[i]);
                BigDecimal bdlng= new BigDecimal(longitud[i]);

                hidcomponente.setComplati(bdlat);
                hidcomponente.setComplong(bdlng);

                hidcomponente.save();
                //      hidnodo.save();
                hidpuntomonitoreo.save();


            }
        }
        return 0;
    }

    public static int EliminarComponentes(String ideliminados)
    {
        String[] eliminados;
        String delimitador = ",";

        //se debe eliminar de la base de datos los componentes que fueron quitados del mapa
        //**al eliminar el componente se elimina el nodo y punto de monitoreo correspondiente
        if(ideliminados.equals("") == false)
        {
            eliminados = ideliminados.split(delimitador);
            for (int i = 0; i < eliminados.length; i++)
            {
                if (Hidcomponente.findById(Integer.valueOf(eliminados[i])) != null)
                {
                    Hidcomponente hidcomponente = Hidcomponente.findById(Integer.valueOf(eliminados[i]));
                    hidcomponente.delete();
                }
            }
        }
        return 0;
    }

    public static int AgregarPolyLines(String lineas, int idmodelo)
    {
        String delimitador = ",";
        System.out.println(lineas);
        //se debe verificar que se han creado componentes de tipo aristas
        if(lineas.equals("") == false)
        {
            String[] polyline = lineas.split(delimitador);

            for(int i = 0; i < polyline.length; i+=10)
            {
                String lat1 = polyline[i];
                String lng1 = polyline[i+1];
                String lat2 = polyline[i+2];
                String lng2 = polyline[i+3];
                String tipo = polyline[i+4];
                String idpoly = polyline[i+5];
                String idnodo1 = polyline[i+6];
                String idnodo2 = polyline[i+7];
                String nombrelinea = polyline[i+8];

                BigDecimal bdlat= new BigDecimal(lat1);
                BigDecimal bdlng= new BigDecimal(lng1);
                BigDecimal bdlat2= new BigDecimal(lat2);
                BigDecimal bdlng2= new BigDecimal(lng2);

                /**PROMEDIO USANDO BIG DECIMAL**/
                BigDecimal bdlat1 = bdlat.add(bdlat2);
                bdlat1 = bdlat1.divide(new BigDecimal( "2" ),14, RoundingMode.UP);

                BigDecimal bdlng1 = bdlng.add(bdlng2);
                bdlng1 = bdlng1.divide(new BigDecimal( "2" ),14, RoundingMode.UP);
                /********************************/

                Hidcomponente hidcomponente;

                //se debe verificar si el componente arista, buscandolos por id o por sus coordenadas


                                System.out.println("TIPO "+ tipo + " IDPOLY "+idpoly);
                if(Hidcomponente.find("byModsimidAndCompid", idmodelo, Integer.valueOf(idpoly)).first() != null)
                {
                    hidcomponente = Hidcomponente.find("byModsimidAndCompid", idmodelo, Integer.valueOf(idpoly)).first();
                }
                else if(Hidcomponente.find("byModsimidAndComplatiAndComplong", idmodelo,bdlat1,bdlng1).first() != null)
                {
                    hidcomponente = Hidcomponente.find("byComplatiAndComplong",bdlat1,bdlng1).first();
                }
                else
                {
                    //si no existe el componente se crea
                    Hidtipocomponente hidtipocomponente = Hidtipocomponente.find("byTipcompnom",tipo).first();
                    Hidmodelosimulacion hidmodelosimulacion = Hidmodelosimulacion.findById(idmodelo);
                    hidcomponente = new Hidcomponente();
                    hidcomponente.setCompid(0);
                    hidcomponente.setCompnom(nombrelinea);
                    hidcomponente.setHidmodelosimulacion(hidmodelosimulacion);
                    hidcomponente.setHidtipocomponente(hidtipocomponente);
                    hidcomponente.setComplati(bdlat1);
                    hidcomponente.setComplong(bdlng1);

                    hidcomponente.save();
                }

                //se debe crear una arista por cada componente
                //**sae debe buscar si existe una arista que corresponda a dicho componente
                Hidarista hidarista;
                if(Hidarista.find("byCompid",hidcomponente.getCompid()).first() != null)
                {
                    hidarista = Hidarista.find("byCompid",hidcomponente.getCompid()).first();
                }
                else
                {
                    hidarista = new Hidarista();
                    hidarista.setArisid(0);
                    hidarista.setHidcomponente(hidcomponente);
                    hidarista.save();
                }

                //**los nodos y aristas se relacionan en funcion de los objetos nodo aristas
                Hidnodoarista hidnodoarista1;
                Hidnodoarista hidnodoarista2;

                List<Hidcomponente> hidcomponentes = Hidcomponente.findAll();
                Hidcomponente hidcomponentetmp;
                Hidcomponente hidcomponente1 = new Hidcomponente();
                Hidcomponente hidcomponente2 = new Hidcomponente();
                int contadorAciertos = 0;

                //se debe verificar si la arista contiene nodos existentes
                for(int i2 = 0; i2 < hidcomponentes.size(); i2++)
                {

                    hidcomponentetmp = hidcomponentes.get(i2);

                    if(Integer.valueOf(idnodo1) == -1 || Integer.valueOf(idnodo1) == 0)
                    {
                        if(hidcomponentetmp.getHidmodelosimulacion().getModsimid() == idmodelo &&
                           hidcomponentetmp.getComplati().compareTo(bdlat) == 0 &&
                           hidcomponentetmp.getComplong().compareTo(bdlng) == 0)
                        {
                            hidcomponente1 = hidcomponentetmp;
                            contadorAciertos++;
                        }
                    }
                    else
                    {
                        if(hidcomponentetmp.getCompid() == Integer.valueOf(idnodo1))
                        {
                            hidcomponente1 = hidcomponentetmp;
                            contadorAciertos++;
                        }
                    }

                    if(Integer.valueOf(idnodo2) == -1 || Integer.valueOf(idnodo2) == 0)
                    {
                        if(hidcomponentetmp.getHidmodelosimulacion().getModsimid() == idmodelo &&
                                hidcomponentetmp.getComplati().compareTo(bdlat2) == 0 &&
                                hidcomponentetmp.getComplong().compareTo(bdlng2) == 0)
                        {
                            hidcomponente2 = hidcomponentetmp;
                            contadorAciertos++;
                        }
                    }
                    else
                    {
                        if(hidcomponentetmp.getCompid() == Integer.valueOf(idnodo2))
                        {
                            hidcomponente2 = hidcomponentetmp;
                            contadorAciertos++;
                        }
                    }

                    if(contadorAciertos == 2)
                    {
                        break;
                    }
                }


                //se asigna los nodos a los objetos nodoarista, para lo cual se debe buscar si el nodoarista
                //si no existe se crean
                Hidnodo hidnodo1 = Hidnodo.find("byCompid",hidcomponente1.getCompid()).first();
                Hidnodo hidnodo2 = Hidnodo.find("byCompid",hidcomponente2.getCompid()).first();

                if(Hidnodoarista.find("byNodidAndArisid",hidnodo1.getNodid(),hidarista.getArisid()).first() != null)
                {
                    hidnodoarista1 = Hidnodoarista.find("byNodidAndArisid",hidnodo1.getNodid(),hidarista.getArisid()).first();
                }
                else
                {
                    hidnodoarista1 = new Hidnodoarista();
                    hidnodoarista1.setNodariid(0);
                    hidnodoarista1.setHidnodo(hidnodo1);
                    hidnodoarista1.setHidarista(hidarista);
                }

                hidnodoarista1.setNodarisinifin(false);

                if(Hidnodoarista.find("byNodidAndArisid",hidnodo2.getNodid(),hidarista.getArisid()).first() != null)
                {
                    hidnodoarista2 = Hidnodoarista.find("byNodidAndArisid",hidnodo2.getNodid(),hidarista.getArisid()).first();
                }
                else
                {
                    hidnodoarista2 = new Hidnodoarista();
                    hidnodoarista2.setNodariid(0);
                    hidnodoarista2.setHidnodo(hidnodo2);
                    hidnodoarista2.setHidarista(hidarista);
                }

                hidnodoarista2.setNodarisinifin(true);

                //se almacena los nodoaristas en la base de datos
                hidnodoarista1.save();
                hidnodoarista2.save();
            }
        }
        return 0;
    }

    public static String obtenerArista(int idComponente)
    {
        Hidarista hidarista = Hidarista.find("byCompid",idComponente).first();
        List<Hidnodoarista> hidnodoaristas = Hidnodoarista.find("byArisid",hidarista.getArisid()).fetch();

        //obtenemos los ids de las aristas conectadas a un nodo
        String aristas = "";
        for(int i = 0; i < hidnodoaristas.size(); i++)
        {
            aristas += hidnodoaristas.get(i).getHidnodo().getHidcomponente().getCompid() + ",";
        }

        //verificamos que al menos exista una as
        if(aristas.equals("") == false)
        {
            aristas += idComponente + "";
        }

        return aristas;
    }

}
